#include <iostream>
#include <unistd.h>
#include <vector>
#include "CPHMediaEngine.h"

using namespace std;

FILE *g_h265File = nullptr;
uint32_t g_frameCount = 0;

void VideoCallbackFunc(uint8_t* data, uint32_t size, VideoCallbackExt& videoCallbackExt) {
	if (g_h265File != nullptr) {
		fwrite(data, size, 1, g_h265File);
	}
	
	g_frameCount++;
	if (g_frameCount > 30) {
		int orientation = (int)videoCallbackExt.orientation;
		std::cout << "orientation:" << orientation
			 << ", startCapture:" << videoCallbackExt.videoLatencyExt.startCaptureTimestamp
			 << ", endCapture:" << videoCallbackExt.videoLatencyExt.endCaptureTimestamp
			 << ", startEncode:" << videoCallbackExt.videoLatencyExt.startEncodeTimestamp
			 << ", endEncode:" << videoCallbackExt.videoLatencyExt.endEncodeTimestamp << std::endl;
		g_frameCount = 0;
	}
}

int main(int argc, char* argv[])
{
	cout << "argc is : " << argc << endl;
	bool bEnableCBR = (argc == 5);
	
	g_h265File = fopen("/data/output.h264", "wb");
	if (g_h265File == nullptr) {
		std::cout << "fopen file failed!" << std::endl;
		return -1;
	}
	
	CPHMediaEngine mediaEngine;
	// 正常720*1280出流json串
	const char *pStr = "{\n"
			"	\"frame_type\": \"h264\", \n"
			"	\"encode_type\": 1,\n"
			"	\"fps\": 30,\n"
			"	\"bitrate\": 2000000,\n"
			"	\"stream_width\": 720,\n"
			"	\"stream_height\": 1280,\n"
			"	\"rcmode\": 3,\n"
			"	\"gop\": 300,\n"
			"	\"profile\": 66,\n"
			"	\"repeat_fps\": 30\n"
			"}";
	// 正常648*1152出流json串
	const char *pStr2 = "{\n"
			"	\"frame_type\": \"h264\", \n"
			"	\"encode_type\": 1,\n"
			"	\"fps\": 30,\n"
			"	\"bitrate\": 2000000,\n"
			"	\"stream_width\": 648,\n"
			"	\"stream_height\": 1152,\n"
			"	\"rcmode\": 3,\n"
			"	\"gop\": 300,\n"
			"	\"profile\": 66,\n"
			"	\"repeat_fps\": 30\n"
			"}";
	// 正常（648*1152）动态修改参数json串
	const char *pStrChange1 = "{\n"
			"	\"fps\": 20,\n"
			"	\"bitrate\": 4000000,\n"
			"	\"stream_width\": 648,\n"
			"	\"stream_height\": 1152,\n"
			"	\"rcmode\": 3,\n"
			"	\"gop\": 3000,\n"
			"	\"profile\": 66,\n"
			"	\"repeat_fps\": 30\n"
			"}";
	
	int iRet = 0;
	int inputChar;
	int inputChar2;
	bool flag = true;
	while (flag) {
		std::cout << "input 1 to set..." << std::endl;
		std::cout << "input 0 to exit..." << std::endl;
		std::cin >> inputChar;
		std::cout << std::endl;
		switch (inputChar) {
			case 1: {
				// CPHMediaEngine 5.0 API
				std::cout << "input 1 to open with correct json1" << std::endl;
				std::cout << "input 2 to open with correct json2" << std::endl;
				std::cout << "input 3 to SetPhysicalResolution as 648*1152" << std::endl;
				std::cout << "input 4 to SetPhysicalResolution as 720*1280" << std::endl;
				std::cout << "input 5 to close mediaEngine" << std::endl;
				std::cout << "input 6 to set params with correct json" << std::endl;
				std::cout << "input 7 to generate key frame" << std::endl;
				
				std::cin >> inputChar2;
				std::cout << std::endl;
				switch (inputChar2) {
					case 1: {
						if (mediaEngine.OpenVideo(pStr, VideoCallbackFunc) != 0) {
							std::cout << "open with correct json failed." << std::endl;
						}
						break;
					}
					case 2: {
						if (mediaEngine.OpenVideo(pStr2, VideoCallbackFunc) != 0) {
							std::cout << "open with correct json failed." << std::endl;
						}
						break;
					}
					case 3: {
						if (mediaEngine.SetPhysicalResolution(648, 1152) != 0) {
							std::cout << "set physical resolution [648*1152] failed!" << std::endl;
						}
						break;
					}
					case 4: {
						if (mediaEngine.SetPhysicalResolution(720, 1280) != 0) {
							std::cout << "set physical resolution [720*1280] failed!" << std::endl;
						}
						break;
					}
					case 5: {
						if (mediaEngine.CloseVideo() != 0) {
							std::cout << "close video failed!" << std::endl;
						}
						if (g_h265File != nullptr) {
							fclose(g_h265File);
							g_h265File = nullptr;
						}
						break;
					}
					case 6: {
						if (mediaEngine.SetParams(pStrChange1) != 0) {
							std::cout << "set params with correct json failed!" << std::endl;
						}
						break;
					}
					case 7: {
						if (mediaEngine.GenerateKeyFrame() != 0) {
							std::cout << "generate key frame failed!" << std::endl;
						}
						break;
					}
					default: {
						std::cout << "wrong!!! pls re-input..." << std::endl;
					}
				}
				break;
			}
			case 0: {
				std::cout << "exit program" << std::endl;
				if (mediaEngine.CloseVideo() != 0) {
					std::cout << "destroy video failed!" << std::endl;
				}
				if (g_h265File != nullptr) {
					fclose(g_h265File);
					g_h265File = nullptr;
				}
				flag = false;
				break;
			}
			default: {
				std::cout << "wrong!!! pls re-input..." << std::endl;
			}
		}
	}

	return 0;
}			